package com.wk.myplayer.player;

import android.media.MediaCodec;
import android.media.MediaFormat;
import android.text.TextUtils;
import android.view.Surface;

import com.wk.myplayer.listener.PlayerCallback;
import com.wk.myplayer.opengl.WlGLSurfaceView;
import com.wk.myplayer.opengl.WlRender;
import com.wk.myplayer.util.WlVideoSupportUitl;
import com.wk.myplayer.bean.WlTimeInfoBean;


import java.nio.ByteBuffer;

public class WlPlayer {

    static {
        System.loadLibrary("simplePlayer");
        System.loadLibrary("avcodec-57");
        System.loadLibrary("avdevice-57");
        System.loadLibrary("avfilter-6");
        System.loadLibrary("avformat-57");
        System.loadLibrary("avutil-55");
        System.loadLibrary("postproc-54");
        System.loadLibrary("swresample-2");
        System.loadLibrary("swscale-4");
    }

    private native void n_parpared(String source);
    private native void n_start();
    private native void n_pause();
    private native void n_resume();
    private native void n_stop();
    private native void n_seek(int secds);


    private String source;
    private WlTimeInfoBean wlTimeInfoBean;
    private boolean playNext = false;

    /**当前播放进度*/
    private int duration = 0;
    private MediaFormat mediaFormat;
    private MediaCodec mediaCodec;
    private Surface surface;
    private MediaCodec.BufferInfo info;
    private PlayerCallback playerCallback ;


    public WlPlayer(PlayerCallback playerCallback){
        this.playerCallback=playerCallback;
    }





    public void setSource(String source) {
        this.source = source;
    }

    public void setWlGLSurfaceView(WlGLSurfaceView glSurfaceView) {
        glSurfaceView.getWlRender().setOnSurfaceCreateListener(new WlRender.OnSurfaceCreateListener() {
            @Override
            public void onSurfaceCreate(Surface s) {
                if(surface == null)   {
                    surface = s;
                }
            }
        });
    }

    public void parpared()  {
        if(TextUtils.isEmpty(source))   {
            playerCallback.onShowLog("parpared ,source not be empty");
            return;
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                n_parpared(source);
            }
        }).start();
    }

    public void start()  {
        if(TextUtils.isEmpty(source)) {
            playerCallback.onShowLog("start ,source not be empty");
            return;
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                n_start();
            }
        }).start();
    }

    public void pause()  {
        n_pause();
        playerCallback.onPause(true);
    }

    public void resume()  {
        n_resume();
        playerCallback.onPause(false);
    }

    public void stop()  {
        wlTimeInfoBean = null;
        duration = 0;
        new Thread(new Runnable() {
            @Override
            public void run() {
                n_stop();
                releaseMediacodec();
            }
        }).start();
    }

    public void seek(int secds)  {
        n_seek(secds);
    }

    public void playNext(String url)  {
        source = url;
        playNext = true;
        stop(); //playNext
    }

    public int getDuration() {
        return duration;
    }


    /**-------------------------- native 回调java的方法---------------------------**/
    public void onCallParpared() {
        playerCallback.onParpared();
    }

    public void onCallLoad(boolean load)  {
        playerCallback.onLoad(load);
    }

    public void onCallTimeInfo(int currentTime, int totalTime) {
        if(wlTimeInfoBean == null)  {
            wlTimeInfoBean = new WlTimeInfoBean();
        }
        duration = totalTime;
        wlTimeInfoBean.setCurrentTime(currentTime);
        wlTimeInfoBean.setTotalTime(totalTime);
        playerCallback.onTimeInfo(wlTimeInfoBean);

    }

    public void onCallError(int code, String msg)  {
        stop(); //onCallError
        playerCallback.onError(code, msg);
    }

    public void onCallComplete()  {
        stop(); //onCallComplete
        playerCallback.onComplete();
    }

    public void onCallNext()  {
        if(playNext)  {
            playNext = false;
            parpared();
        }
    }


    public boolean onCallIsSupportMediaCodec(String ffcodecname)  {
        playerCallback.onShowLog("onCallIsSupportMediaCodec , ffcodecname="+ffcodecname);
        return WlVideoSupportUitl.isSupportCodec(ffcodecname);
    }


    public void initMediaCodec(String codecName, int width, int height, byte[] csd_0, byte[] csd_1)  {
        playerCallback.onShowLog("initMediaCodec , codecName="+codecName);
        if(surface != null)  {
            try {
                String mime = WlVideoSupportUitl.findVideoCodecName(codecName);
                mediaFormat = MediaFormat.createVideoFormat(mime, width, height);
                mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, width * height);
                mediaFormat.setByteBuffer("csd-0", ByteBuffer.wrap(csd_0));
                mediaFormat.setByteBuffer("csd-1", ByteBuffer.wrap(csd_1));

                mediaCodec = MediaCodec.createDecoderByType(mime);
                info = new MediaCodec.BufferInfo();
                mediaCodec.configure(mediaFormat, surface, null, 0);
                mediaCodec.start();

            } catch (Exception e)  {
                playerCallback.onError(2001, "initMediaCodec,"+e.getMessage());
                e.printStackTrace();
            }
        } else  {
            playerCallback.onError(2001, "surface is null");

        }
    }

    /*
      decodeAVPacket。
      硬解码方式，底层FFmpeg 获得264帧数据，用Java层的mediacodec来解码播放
     */
    public void decodeAVPacket(int datasize, byte[] data)  {
        if(surface != null && datasize > 0 && data != null && mediaCodec != null)  {
            try  {
                int intputBufferIndex = mediaCodec.dequeueInputBuffer(10);
                if(intputBufferIndex >= 0)   {
                    ByteBuffer byteBuffer = mediaCodec.getInputBuffers()[intputBufferIndex];
                    byteBuffer.clear();
                    byteBuffer.put(data);
                    mediaCodec.queueInputBuffer(intputBufferIndex, 0, datasize, 0, 0);
                }

                int outputBufferIndex = mediaCodec.dequeueOutputBuffer(info, 10);
                while(outputBufferIndex >= 0)  {
                    mediaCodec.releaseOutputBuffer(outputBufferIndex, true);
                    outputBufferIndex = mediaCodec.dequeueOutputBuffer(info, 10);
                }
            } catch (Exception e)  {
                playerCallback.onError(2001, "decodeAVPacket,"+e.getMessage());
                e.printStackTrace();
            }
        }
    }

    private void releaseMediacodec()  {
        if(mediaCodec != null)  {
            try {
                mediaCodec.flush();
                mediaCodec.stop();
                mediaCodec.release();
            }
            catch(Exception e)  {
                playerCallback.onError(2001, "releaseMediacodec,"+e.getMessage());
            }
            mediaCodec = null;
            mediaFormat = null;
            info = null;
        }
    }

}
